package gameoflife.automaton;

import gameoflife.ChangeListener;
import gameoflife.Position;
import gameoflife.Rule;

import java.util.ArrayList;
import java.util.List;

public abstract class AbstractAutomaton implements Automaton {

	protected Rule rule = Rule.LIFE;
	protected int generation = 0;

	private List<ChangeListener> listeners = new ArrayList<ChangeListener>();

	@Override
	public synchronized void step(int steps) {
		for (int step = 0; step < steps; step++) {
			step();
		}
		stateChanged(Automaton.STEP_CHANGE_CODE);
	}

	protected abstract void step();

	@Override
	public void toggle(Position position) {
		set(position, !isSet(position));	
	}

	@Override
	public synchronized int generation() {
		return generation;
	}

	@Override
	public synchronized Rule getRule() {
		return rule;
	}

	@Override
	public synchronized void setRule(Rule rule) {
		this.rule = rule;
		stateChanged(0);
	}

	@Override
	public synchronized void addChangeListener(ChangeListener listener) {
		listeners.add(listener);
	}

	protected void stateChanged(int changeCode) {
		for (ChangeListener listener : listeners) {
			listener.stateChanged(changeCode);
		}
	}
}
